using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.Json.Serialization;

namespace RBAC.Read.Api.Application.Services
{
    /// <summary>
    /// 规则定义（轻量阈值型）。
    /// 指标支持：temp、wind_speed、humidity、rain、pop。
    /// 运算符支持：gt、gte、lt、lte、eq。
    /// </summary>
    public class RiskRuleDto
    {
        public string Id { get; set; } = Guid.NewGuid().ToString("N");
        // 指标：temp | wind_speed | humidity | rain | pop
        public string Metric { get; set; } = "temp";
        // 运算符：gt | gte | lt | lte | eq
        public string Op { get; set; } = "gt";
        public double Value { get; set; }
        // 评估窗口（小时）
        public int WindowHours { get; set; } = 24;
        public string? Advice { get; set; }
        // low/medium/high（可选，未命中默认low，命中默认medium）
        public string? Severity { get; set; }
    }

    /// <summary>
    /// 单条规则评估结果。
    /// </summary>
    public class RiskRuleResult
    {
        public string RuleId { get; set; } = string.Empty;
        public bool Matched { get; set; }
        public int Occurrences { get; set; }
        public int WindowHours { get; set; }
        public string? Advice { get; set; }
        public string Severity { get; set; } = "low";
        // 英文指标（仅内部使用）
        [JsonIgnore]
        public string? Metric { get; set; }
        public string? MetricZh { get; set; }
    }

    /// <summary>
    /// 风险评估响应。
    /// </summary>
    public class EvaluateRiskResponse
    {
        public string Summary { get; set; } = "low"; // 输出时会映射为：低/中/高
        public List<RiskRuleResult> Results { get; set; } = new();
    }

    /// <summary>
    /// 风险评估请求。
    /// </summary>
    public class EvaluateRiskRequest
    {
        public double Lat { get; set; }
        public double Lon { get; set; }
        public int Hours { get; set; } = 24;
        public string Units { get; set; } = "metric";
        public List<RiskRuleDto> Rules { get; set; } = new();
    }

    /// <summary>
    /// 风险评估器接口。
    /// </summary>
    public interface IRiskEngine
    {
        /// <summary>
        /// 评估给定预报数据在指定规则下的风险。
        /// </summary>
        EvaluateRiskResponse Evaluate(ForecastDto forecast, IEnumerable<RiskRuleDto> rules);
    }

    /// <summary>
    /// 简单阈值型风险评估实现。
    /// 注意：生产可替换为 JSONLogic/CEL 等可配置规则引擎。
    /// </summary>
    public class RiskEngine : IRiskEngine
    {
        private static string ToZhSeverity(string? level)
        {
            return level switch
            {
                "high" => "高",
                "medium" => "中",
                "low" => "低",
                _ => level ?? string.Empty
            };
        }
        private static string ToZhMetric(string? metric)
        {
            return metric switch
            {
                "temp" => "温度",
                "wind_speed" => "风速",
                "humidity" => "湿度",
                "rain" => "降雨量",
                "pop" => "降水概率",
                _ => metric ?? string.Empty
            };
        }
        public EvaluateRiskResponse Evaluate(ForecastDto forecast, IEnumerable<RiskRuleDto> rules)
        {
            var hourly = forecast.Hourly ?? new();
            var result = new EvaluateRiskResponse();
            foreach (var rule in rules)
            {
                int occurrences = 0;
                var window = Math.Min(rule.WindowHours, hourly.Count);
                for (int i = 0; i < window; i++)
                {
                    var h = hourly[i];
                    double metric = rule.Metric switch
                    {
                        "temp" => h.Temp,
                        "wind_speed" => h.WindSpeed,
                        "humidity" => h.Humidity,
                        "rain" => h.Rain,
                        "pop" => h.Pop,
                        _ => double.NaN
                    };
                    if (double.IsNaN(metric)) continue;
                    bool ok = rule.Op switch
                    {
                        "gt" => metric > rule.Value,
                        "gte" => metric >= rule.Value,
                        "lt" => metric < rule.Value,
                        "lte" => metric <= rule.Value,
                        "eq" => Math.Abs(metric - rule.Value) < 1e-9,
                        _ => false
                    };
                    if (ok) occurrences++;
                }
                var matched = occurrences > 0;
                // 未命中时一律视为 low；命中时采用规则给定严重级别，否则默认 medium
                var severityEn = matched ? (rule.Severity ?? "medium") : "low";
                result.Results.Add(new RiskRuleResult
                {
                    RuleId = rule.Id,
                    Matched = matched,
                    Occurrences = occurrences,
                    WindowHours = rule.WindowHours,
                    Advice = rule.Advice,
                    Severity = ToZhSeverity(severityEn),
                    Metric = rule.Metric,
                    MetricZh = ToZhMetric(rule.Metric)
                });
            }
            // 根据英文级别来判断汇总，再转换为中文输出
            var anyHigh = result.Results.Any(r => r.Severity == ToZhSeverity("high"));
            var anyMatch = result.Results.Any(r => r.Matched);
            var summaryEn = anyHigh ? "high" : (anyMatch ? "medium" : "low");
            result.Summary = ToZhSeverity(summaryEn);
            return result;
        }
    }
}
